/**   
* @Title: ObjectUtils.java
* @Package com.jbeer.framework.utils
* @author Bieber
* @date 2014-3-9 下午02:41:11
* @version V1.0   
*/

package com.jbeer.framework.utils;

import java.io.File;
import java.lang.reflect.Array;
import java.lang.reflect.Field;
import java.lang.reflect.GenericArrayType;
import java.lang.reflect.Method;
import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type;
import java.util.ArrayList;
import java.util.Collection;
import java.util.HashMap;
import java.util.HashSet;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Set;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

import com.jbeer.framework.exception.InitObjectException;

/**
 * <p>类功能说明:对象工具类</p>
 * <p>类修改者	    修改日期</p>
 * <p>修改说明</p>
 * <p>Title: ObjectUtils.java</p>
 * @author Bieber <a mailto="bieber.jbeer@hotmail.com">bieber.jbeer@hotmail.com</a>
 * @date 2014-3-9 下午02:41:11
 * @version V1.0
 */

public class ObjectUtils {
	
	
	/**
	 * 
	 * <p>
	 * 函数功能说明:对象封装者，设置对象相关属性值
	 * </p>
	 * <p>
	 * Bieber 2014-3-8
	 * </p>
	 * <p>
	 * 修改者名字 修改日期
	 * </p>
	 * <p>
	 * 修改内容</a>
	 * 
	 * @return Object
	 */
	@SuppressWarnings({ "unchecked", "rawtypes" })
	public static Object objectWrapper(Object object,
			Map<String, Object> parameters) throws InitObjectException {
		Object instance = object;
		Class<?> type = object.getClass();
		try {
			if (parameters == null) {
				return instance;
			}
			parameters = analyseRequestParameters(parameters);
			Set<String> keys = parameters.keySet();
			for (String key : keys) {
				Object value = parameters.get(key);
				Field field=null;
				try{
				 field = type.getDeclaredField(key);
				}catch(NoSuchFieldException e){
					continue;
				}
				field.setAccessible(true);
				Method setMethod = ClassUtils.searchSetMethod(type, key,
						field.getType());
				if (setMethod != null) {
					Class<?> paramTypes = setMethod.getParameterTypes()[0];

					Object fieldValue = null;
					/**
					 * 表示这个是一个数组，并且该数组是一个非基础类型的数组
					 */
					if (value.getClass().getComponentType() == Map.class) {
						Map[] maps = (Map[]) value;
						/**
						 * 对象集合
						 */
						if (Collection.class.isAssignableFrom(paramTypes)) {
							Collection collec = initCollection(paramTypes);
							Type generType = field.getGenericType();
							ParameterizedType ptype = (ParameterizedType) generType;
							Type actualType = ptype
							.getActualTypeArguments()[0];
							Class<?> clazz = null;
							if(Class.class.isAssignableFrom(actualType.getClass())){
								clazz=(Class<?>) ptype
								.getActualTypeArguments()[0];
							}else if(ParameterizedType.class.isAssignableFrom(actualType.getClass())){
								ParameterizedType tempType = (ParameterizedType) actualType;
								clazz = (Class<?>) tempType.getRawType();
							}
							for (Map map : maps) {
								if (map == null) {
									continue;
								}
								Object objectInstance = null;
								if (Map.class.isAssignableFrom(clazz)) {// 检查是否是一个map集合
									Class<?> keyClass = String.class;
									Class<?> valueClass = String.class;
									findMapGenericType(field, keyClass,
											valueClass);
									objectInstance = newMapInstance(map,
											keyClass, valueClass);
								} else {
									objectInstance = objectWrapper(clazz.newInstance(), map);
								}
								collec.add(objectInstance);
							}
							fieldValue = collec;
						} else if (paramTypes.getComponentType() != null) {// 对象数组
							Object[] values =  initObjectArray(paramTypes.getComponentType(),maps.length);
							for (int i = 0; i < values.length; i++) {
								if (maps[i] == null) {
									continue;
								}
								Object objectInstance = null;
								if (Map.class.isAssignableFrom(paramTypes
										.getComponentType())) {// 检查是否是一个map数组
									Class<?> keyClass = String.class;
									Class<?> valueClass = String.class;
									findMapGenericType(field, keyClass,
											valueClass);
									objectInstance = newMapInstance(maps[i],
											keyClass, valueClass);
								} else {
									objectInstance = objectWrapper(
											paramTypes.getComponentType().newInstance(),
											maps[i]);
								}
								values[i] = objectInstance;
							}
							fieldValue = values;
						} else if (Map.class.isAssignableFrom(paramTypes)) {// 单个map对象
							Type generType = field.getGenericType();
							ParameterizedType ptype = (ParameterizedType) generType;
							Class<?> keyClass = null;
							Class<?> valueClass = null;
							if (ptype.getActualTypeArguments().length > 0) {
								keyClass = (Class<?>) ptype
										.getActualTypeArguments()[0];
								valueClass = (Class<?>) ptype
										.getActualTypeArguments()[1];
							}
							fieldValue = newMapInstance(maps[0], keyClass,
									valueClass);
						} else {// 单个对象
							if (maps[0] != null) {
								fieldValue = objectWrapper(paramTypes.newInstance(), maps[0]);
							}
						}
					} else {// 进行一些基础类型的属性赋值
						Object[] valueArray = (Object[]) value;
						if (paramTypes.getComponentType() == null) {
							if (CaseUtils.checkIsBasicType(paramTypes)) {
								fieldValue = CaseUtils.caseType(paramTypes,
										valueArray[0].toString());
							} else if (paramTypes == File.class) {
								fieldValue = valueArray[0];
							} else {
								if (Collection.class.isAssignableFrom(field
										.getType())) {
									Collection collec = initCollection(field
											.getType());
									Type generType = field.getGenericType();
									ParameterizedType ptype = (ParameterizedType) generType;
									Class<?> clazz = (Class<?>) ptype
											.getActualTypeArguments()[0];
									if (collec != null) {
										for (Object val : valueArray) {
											collec.add(CaseUtils.caseType(
													clazz, val.toString()));
										}
									}
									fieldValue = collec;
								}
							}
						} else {// 如果执行这里，表示参数是一个数组，则直接将值赋给该属性
							Object[] values = (Object[]) Array.newInstance(
									paramTypes.getComponentType(),
									valueArray.length);
							for (int i = 0; i < valueArray.length; i++) {
								values[i] = CaseUtils.caseType(
										paramTypes.getComponentType(),
										valueArray[i].toString());
							}
							fieldValue = values;
						}
					}
					setMethod.invoke(instance, fieldValue);
				}
			}
		} catch (Exception e) {
			throw new InitObjectException(e);
		}
		return instance;
	}
	
	/**
	 * 
	 * <p>
	 * 函数功能说明:初始化一个Map对象
	 * </p>
	 * <p>
	 * Bieber 2014-3-9
	 * </p>
	 * <p>
	 * 修改者名字 修改日期
	 * </p>
	 * <p>
	 * 修改内容</a>
	 * 
	 * @return Map
	 */
	@SuppressWarnings({ "rawtypes", "unchecked" })
	private static Map newMapInstance(Map temp, Class<? extends Object> keyClass,
			Class<?> valueClass) {
		Map map = new HashMap();
		Set<Entry> entries = temp.entrySet();
		for (Entry entry : entries) {
			Object[] valueArray = (Object[]) entry.getValue();
			if (keyClass == null && valueClass == null) {
				map.put(entry.getKey(), valueArray[0]);
			} else {
				map.put(CaseUtils.caseType(keyClass, entry.getKey().toString()),
						CaseUtils.caseType(valueClass, valueArray[0].toString()));
			}
		}
		return map;
	}

	/**
	 * 
	 * <p>
	 * 函数功能说明:获取Map泛型类型
	 * </p>
	 * <p>
	 * Bieber 2014-3-9
	 * </p>
	 * <p>
	 * 修改者名字 修改日期
	 * </p>
	 * <p>
	 * 修改内容</a>
	 * 
	 * @return void
	 */
	private static void findMapGenericType(Field field, Class<?> keyClass,
			Class<?> valueClass) {
		Type type = field.getGenericType();
		/**
		 * 数组的泛型
		 */
		if (GenericArrayType.class.isAssignableFrom(type.getClass())) {
			GenericArrayType arrayType = (GenericArrayType) type;
			Type componentType = arrayType.getGenericComponentType();
			if (ParameterizedType.class.isAssignableFrom(componentType
					.getClass())) {
				ParameterizedType parameterizedType = (ParameterizedType) componentType;
				Type[] types = parameterizedType.getActualTypeArguments();
				if (types != null && types.length > 0) {
					keyClass = (Class<?>) types[0];
					valueClass = (Class<?>) types[1];
				}
			}
		} else if (ParameterizedType.class.isAssignableFrom(type.getClass())) {// 集合的泛型
			ParameterizedType parameterizedType = (ParameterizedType) type;
			Type[] types = parameterizedType.getActualTypeArguments();
			Type paramType = types[0];
			if (ParameterizedType.class.isAssignableFrom(paramType.getClass())) {
				ParameterizedType tempType = (ParameterizedType) paramType;
				Type[] tempTypes = tempType.getActualTypeArguments();
				if (tempTypes != null && tempTypes.length > 0) {
					keyClass = (Class<?>) tempTypes[0];
					valueClass = (Class<?>) tempTypes[1];
				}
			}
		}
	}

	/**
	 * 
	 * <p>
	 * 函数功能说明:初始化集合对象
	 * </p>
	 * <p>
	 * Bieber 2014-3-8
	 * </p>
	 * <p>
	 * 修改者名字 修改日期
	 * </p>
	 * <p>
	 * 修改内容</a>
	 * 
	 * @return Collection
	 */
	@SuppressWarnings("rawtypes")
	private static Collection initCollection(Class<?> type) {
		if (List.class.isAssignableFrom(type)) {
			return new ArrayList();
		} else if (Set.class.isAssignableFrom(type)) {
			return new HashSet();
		} else if (LinkedList.class.isAssignableFrom(type)) {
			return new LinkedList();
		} else {
			return null;
		}
	}

	/**
	 * 
	 * <p>
	 * 函数功能说明:对request的请求参数进行分析，从而可以进行将参数封装到controller中
	 * </p>
	 * <p>
	 * Bieber 2014-3-8
	 * </p>
	 * <p>
	 * 修改者名字 修改日期
	 * </p>
	 * <p>
	 * 修改内容</a>
	 * 
	 * @return Map<String,Object>
	 */
	@SuppressWarnings("unchecked")
	protected static Map<String, Object> analyseRequestParameters(
			Map<String, Object> parameters) {
		Pattern pattern = Pattern.compile("\\[[0-9]*\\]");
		Map<String, Object> analyseResult = new HashMap<String, Object>();
		Set<String> keys = parameters.keySet();
		for (String key : keys) {
			Object value = parameters.get(key);
			String[] items = key.split("\\.", 2);
			Matcher matcher = pattern.matcher(items[0]);
			int index = 0;
			boolean found = matcher.find();

			if (found) {
				index = Integer.parseInt(matcher.group().replaceAll("[\\[\\]]",
						""));
			}
			String newItem = matcher.replaceAll("");
			if (items.length > 1) {
				Map<String, Object>[] itemValues = (Map<String, Object>[]) analyseResult
						.get(newItem);
				if (itemValues == null) {
					itemValues = new Map[index + 1];
					Map<String, Object> itemValue = new HashMap<String, Object>();
					itemValues[index] = itemValue;
					itemValue.put(items[1], value);
					analyseResult.put(newItem, itemValues);
				} else {
					if (itemValues.length > index) {
						if (itemValues[index] == null) {
							itemValues[index] = new HashMap<String, Object>();
						}
						itemValues[index].put(items[1], value);
					} else {
						Map<String, Object>[] dest = new Map[index + 1];
						System.arraycopy(itemValues, 0, dest, 0,
								itemValues.length);
						dest[index] = new HashMap<String, Object>();
						dest[index].put(items[1], value);
						analyseResult.put(newItem, dest);
					}
				}
			} else {
				if (found) {
					Object[] valArray = (Object[]) value;
					WebUtils.addParametervalue(analyseResult, newItem,
							valArray[0]);
				} else {
					analyseResult.put(newItem, value);
				}
			}
		}
		return analyseResult;
	}

	private static Object[] initObjectArray(Class<?> type,int size){
			return (Object[]) Array.newInstance(type, size);
	}
}
